//ini file i/o
//$Id: ini_file.h 97 2009-08-26 15:11:42Z Oleg.Bulychov $
#pragma once

//"MIT license is an academic license"
#include "contrib/simpleini/SimpleIni.h"

#include "src/heo/include/reflection.h"

//__________________________________________________________________________________
namespace ini
{
//__________________________________________________________________________________
class in:
    public meta::visitor<in>
{
    CSimpleIniA ini_;
    std::string section_;
    SI_Error    load_error_;
public:
    in(char const* szFile)
    {
        load_error_ = ini_.LoadFile(szFile);//TODO fix me: bad design?
    }

    template<class T>
    void load(T& t, char const* szSection)
    {
        section_ = szSection;
        visit_T(t, "", 0);
    }

    bool load_Error()
    {
        return SI_FILE == load_error_;
    }

    template<typename T, typename D>
    void visit(T& t, char const* szName, D const& d)
    {
        if (!*szName)
            return;
        char const* def = "";
        char const* value = ini_.GetValue(section_.c_str(), szName, def);
        if (def == value)
            meta::Set_Default(t, d);
        else
        {
            meta::From_String(t, szName, value, d);
        }
    }

    template<typename T, typename D>
    void visit_Array(T* pt, size_t N, char const* szName, D const& d)
    {}
    template<typename T, typename D>
    void visit_Ptr(T* pt, char const* szName, D const& d)
    {}
};
//__________________________________________________________________________________
//__________________________________________________________________________________
class out:
    public meta::visitor<out>
{
    CSimpleIniA ini_;
    std::string file_;
    std::string section_;
public:
    out(char const* szFile): file_(szFile)
    {}

    ~out()
    {
        ini_.SaveFile(file_.c_str());
    }

    template<class T>
    void save(T& t, char const* szSection)
    {
        section_ = szSection;
        visit_T(t);
    }

    template<typename T, typename D>
    void visit(T& t, char const* szName, D const& d)
    {
        if (!*szName)
            return;
        std::string s;
        char const* str = meta::Value2String(t, s);
        ini_.SetValue(section_.c_str(), szName, str);
    }

    template<typename T, typename D>
    void visit_Array(T* pt, size_t N, char const* szName, D const& d)
    {}
    template<typename T, typename D>
    void visit_Ptr(T* pt, char const* szName, D const& d)
    {}
};
//__________________________________________________________________________________
}//ini
//__________________________________________________________________________________

//EOF!
